<template>
  <div>
    <el-card>
      <!-- 表单 -->
      <el-form
        rules=""
        ref="goodsRef"
        :model="goodsForm"
        label-width="120"
      >
        <el-form-item
          prop=""
          label="商品名称"
        >
          <el-input
            placeholder="请输入商品名称"
            v-model="goodsForm.name"
          ></el-input>
        </el-form-item>

        <el-form-item
          prop=""
          label="分类名称"
        >
          <el-select
            v-model="goodsForm.categoryId"
            placeholder="请选择类别"
            style="width: 240px"
          >
            <el-option-group
              v-if="tree.length > 0"
              v-for="group in tree"
              :key="group.name"
              :label="group.name"
            >
              <el-option
                v-for="item in group.children"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              />
            </el-option-group>
          </el-select>
        </el-form-item>

        <el-form-item
          prop=""
          label="商品价格"
        >
          <el-input
            placeholder="请输入商品名称"
            v-model="goodsForm.price"
          ></el-input>
        </el-form-item>

        <!-- 商品图片 -->
        <el-form-item
          prop=""
          label="商品图片"
        >
          <el-upload
            :http-request="null"
            :limit="1"
            ref="uploadRef"
            v-model:file-list="goodsPic"
            class="upload-demo"
            :on-exceed="handleExceed"
            :on-remove="removePic"
            :before-upload="beforeUpload"
            :on-change="progressPic"
          >
            <el-button type="primary">上 传</el-button>
            <template #tip>
              <div class="el-upload__tip">
                图片大小不超过500KB <strong style="color: red">仅限上传一张图片 新图片会覆盖旧图片</strong>
              </div>
            </template>
          </el-upload>
        </el-form-item>

        <!-- 图片列表 -->
        <el-form-item
          prop=""
          label="图片相册"
        >
          <el-upload
            v-model:file-list="goodsPicList"
            action=""
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :http-request="submitList"
            :before-upload="beforeUpload"
            :on-remove="listRemove"
          >
            <el-icon>
              <Plus />
            </el-icon>
          </el-upload>
        </el-form-item>

        <el-form-item
          prop=""
          label="商品库存"
        >
          <el-input
            placeholder="请输入商品库存"
            v-model="goodsForm.stock"
          ></el-input>
        </el-form-item>
        <el-form-item
          prop=""
          label="商品规格"
        >
          <el-input
            placeholder="请输入商品规格"
            v-model="goodsForm.spec"
          ></el-input>
        </el-form-item>

        <!-- 富文本编辑器 -->
        <el-form-item
          prop=""
          label="商品简介"
        >
          <div style="border: 1px solid #ccc">
            <Toolbar
              style="border-bottom: 1px solid #ccc"
              :editor="editorRef"
              :defaultConfig="toolbarConfig"
            />
            <Editor
              style="height: 500px; overflow-y: hidden"
              v-model="goodsForm.description"
              :defaultConfig="editorConfig"
              @onCreated="handleCreated"
            />
          </div>
        </el-form-item>
        <!-- 按钮 -->
        <el-form-item>
          <el-button
            type="primary"
            @click="submit"
          >
            {{ GOODS_BUTTON_MAP[curEditType] }}
          </el-button>
          <el-button @click="reset">重 置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup>
  import '@wangeditor/editor/dist/css/style.css' // 引入 css
  import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
  import { onBeforeUnmount, ref, shallowRef, defineProps, defineEmits, reactive } from 'vue'
  import { GOODS_STATUS, GOODS_BUTTON_MAP } from '../constants/Goods'
  import { getDetail, add, update, submitPic } from '../api/apiByGoods'
  import { saveList, getListByGoodsId } from '../api/apiByGoodsAlbum'
  import { BASE_URL } from '../config/urlConfig.js'
  import { getAllList } from '../api/apiByCategory'
  import { ElMessage } from 'element-plus'
  import { useTokenStore } from '../store/tokenStore.js'
  import { IMG_MAX_SIZE } from '../constants/File.js' // 图片限制大小 （单位是字节）
  const { token } = useTokenStore()

  // 商品单个图片
  const goodsPic = ref([])
  // 不需要处理url 的地址
  const NO_DEAL_URL_START = ['static'] // 开头
  // 不需要处理url 的地址
  const DEAL_URL_CONTAIN = ['myAdd'] // 包含

  // 商品存储路径
  const GOODS_BASIC_PATH = 'upload/image/goods/myAdd'
  const uploadRef = ref(null)

  const { curEditType, goodsId } = defineProps({
    curEditType: {
      require: true,
      type: String,
    },
    goodsId: {
      type: Number,
    },
  })
  const emits = defineEmits()

  const goodsRef = ref(null)
  const goodsForm = reactive({
    id: goodsId,
    categoryId: '',
    name: '',
    price: '',
    picture: '',
    stock: '',
    spec: '',
    description: '',
  })

  const tree = ref([])

  const convertToTree = (data) => {
    const treeData = []
    const map = {}
    // 遍历一维数组数据，建立节点映射表
    for (const item of data) {
      map[item.id] = { ...item, children: [] }
    }
    // 遍历映射表，将节点添加到父节点的 children 中
    for (const item of data) {
      const node = map[item.id]
      if (item.pid === 0) {
        treeData.push(node)
      } else {
        const parent = map[item.pid]
        parent.children.push(node)
      }
    }
    return treeData
  }

  // 获取分类列表并处理为树形
  async function getCategoryList() {
    let list = await getAllList()
    tree.value = convertToTree(list)
  }
  getCategoryList()

  // 富文本编辑器
  // 编辑器实例，必须用 shallowRef
  const editorRef = shallowRef()
  const toolbarConfig = {}
  const editorConfig = {
    placeholder: '请输入内容...',
    MENU_CONF: {
      // 上传图片的配置
      uploadImage: {
        // 必填 请求地址
        server: `${BASE_URL}goods/submitPic`,

        // file 文件的字段名
        fieldName: 'file',
        // 其他传递的参数， 加在 formData 中
        meta: {
          dest: `${GOODS_BASIC_PATH}/list`,
        },

        // 请求头：存放 token
        headers: {
          Token: token,
        },

        // 单个文件的最大体积限制，默认为 2M
        maxFileSize: 0.5 * 1024 * 1024, // 512kb

        // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
        allowedFileTypes: ['image/*'],

        // 上传前的回调
        onBeforeUpload(file) {
          const {data} = Object.values(file)[0]
          if (!beforeUpload(data)) {
            return false
          }          
          return file;
        },
        // 上传成功
        onSuccess(file, res) {
          console.log(` 上传成功`, res)
        },
        // 单个文件上传失败
        onFailed(file, res) {
          // console.log(`${BASE_URL}goods/submitPic`)
          // console.log(` 上传失败`, res)
        },

        // 上传错误，或者触发 timeout 超时
        onError(file, err, res) {
          ElMessage.error('文件太大，请重新上传文件')
          // console.log(`传出错`, err)
          // console.log(`上传出错`, res)
        },

        // 自定义插入图片
        customInsert(res, insertFn) {
          // res 即服务端的返回结果
          // 从 res 中找到 url alt href ，然后插入图片
          const { data: url, alt, href } = res
          insertFn(BASE_URL + url, alt, href)
        },

        // 自定义上传
        // async customUpload(file, insertFn) {
        //   // 自己实现上传，并得到图片 url alt href
        //   // 最后插入图片
        //   const { data: url, alt, href } = await submitPic(file)
        //   insertFn(BASE_URL + url, alt, href)
        // }
      },
    },
  }

  // 组件销毁时，也及时销毁编辑器
  onBeforeUnmount(() => {
    const editor = editorRef.value
    if (editor == null) return
    editor.destroy()
  })

  const handleCreated = (editor) => {
    // editor.customConfig.uploadFileName = 'file'
    editorRef.value = editor // 记录 editor 实例，重要！
  }

  // 商品图片
  // 返回的图片列表（返回给后台的）
  let picList = []

  // 获取商品详情
  async function getDetailById(goodsId) {
    if (!goodsId) return
    const goodsDetail = await getDetail(goodsId)
    for (let key in goodsDetail) {
      goodsForm[key] = goodsDetail[key]
    }
    // 回显单个图片
    updatePic(goodsForm.picture)
  }
  getDetailById(goodsId)

  // 文件上传前判断
  function beforeUpload(file) {
    if (file.size > IMG_MAX_SIZE) {
      ElMessage.error('文件太大，请重新上传文件')
      return false
    }
    return true
  }

  // 上传单个图片
  const progressPic = async (file) => {
    if (!beforeUpload(file)) return
    // 赋值
    goodsForm.picture = await upload(file.raw, '/single')
    // 更新单个图片 (不用更新 因为组件会自动更新)
    // updatePic(goodsForm.picture)
  }

  const removePic = () => {
    goodsForm.picture = ''
  }

  // 回显/更新单个图片
  function updatePic(url) {
    if (!url) return
    let lastIndex = url.lastIndexOf('/')
    let len = url.length
    let name = url.slice(lastIndex + 1 - len)
    // 判断是否需要处理名字
    let flag = 0 // 1 表示需要处理 默认是不需要处理
    // for (let item of NO_DEAL_URL_START) {
    // 	// item: static
    // 	console.log(url, item, url.includes(item))
    // 	if (url.startsWith(item)) {
    // 		// 不需要处理...
    // 		flag = 0
    // 		break
    // 	}
    // }
    // console.log(DEAL_URL_CONTAIN)
    for (let item of DEAL_URL_CONTAIN) {
      // 需要处理的
      if (url.includes(item)) {
        flag = 1
        break
      }
    }

    if (flag) {
      // 移除前面的 UUID
      name = name.slice(36)
    }
    // 删除
    if (goodsPic.value.length > 1) goodsPic.value.splice(0, 1)
    goodsPic.value.push({ url, name })
  }

  // 上传列表图片
  const submitList = async (param) => {
    let picture = await upload(param.file, '/list')
    // 添加到图片列表
    picList.push({
      uid: param.file.uid,
      goodsId,
      picture,
    })
  }
  // 图片上传
  const upload = (file, path) => {
    console.log(file)
    return submitPic({ file, dest: GOODS_BASIC_PATH + path })
  }

  // 图片超出
  const handleExceed = (files) => {
    // 文件太大 就不要更新
    if (!beforeUpload(files[0])) return
    const file = files[0]
    uploadRef.value.clearFiles()
    // file.uid = genFileId()
    uploadRef.value.handleStart(file)
  }

  // 图片列表(显示出去的)
  const goodsPicList = ref([])

  // 从列表中移除单个图片
  const listRemove = (file, files) => {
    picList.forEach((e, i) => {
      if (e.id === file.id || e.uid === file.uid) return picList.splice(i, 1)
    })
  }
  // 将后端的数据变为前端可处理的数据
  async function endToFrontOfPicList() {
    let result = await getListByGoodsId(goodsId)
    let list = []
    picList = result // 赋值给后台
    result.forEach((item) => {
      const { id, picture } = item
      list.push({ id, url: picture })
    })
    goodsPicList.value = list
  }
  // 文件编辑是添加状态 的时候不用执行
  curEditType !== GOODS_STATUS.add && endToFrontOfPicList()

  // 提交
  async function submit() {
    if (!goodsForm.categoryId)
      return ElMessage({
        message: '分类名称不能为空',
        type: 'error',
      })
    let id
    // 根据当前状态来获取对应的接口
    if (curEditType === GOODS_STATUS.add) {
      id = await add(goodsForm)
    } else if (curEditType === GOODS_STATUS.modify) {
      update(goodsForm)
    }

    // 更新商品图片相册
    saveList(picList, goodsId || id)
    // finish
    emits('finish')
  }
</script>

<style scoped></style>
